Popular Searches
Popular Course Categories
Popular Courses

Stack and Positioned Widgets

Stack and Positioned Widgets

Flutter Layout & UI Design

Stack and Positioned Widgets in Flutter

Stack and Positioned are important Flutter widgets for creating layered user interfaces. They allow multiple widgets to overlap each other and make it possible to place individual widgets at specific positions inside a parent area.

Stack is useful for interfaces such as image overlays, profile badges, floating buttons, banners, cards, notification indicators, gradients over images, custom headers, and layered dashboard components.


1. What Is the Stack Widget?

The Stack widget places its children relative to the edges of its available box and allows multiple children to overlap one another.

Unlike Row and Column, which normally arrange children next to each other, Stack places children on top of each other.

Stack
├── Background
├── Image
├── Overlay
├── Text
└── Button

2. Basic Stack Syntax

Stack(
  children: [
    Container(
      width: 300,
      height: 200,
      color: Colors.blue,
    ),
    const Text('Hello Flutter'),
  ],
)

In this example, the Text is painted above the Container because it appears later in the children list.

3. How Stack Works

A Stack contains two general types of children:

  • Non-positioned children: Normal children that are not controlled by Positioned.
  • Positioned children: Children wrapped with Positioned and given positioning values such as top, left, right, or bottom.

The Stack uses its non-positioned children when determining its size. Positioned children are then placed relative to the Stack according to their positioning properties.

4. Simple Stack Example

Stack(
  children: [
    Container(
      width: 250,
      height: 250,
      color: Colors.red,
    ),
    Container(
      width: 200,
      height: 200,
      color: Colors.green,
    ),
    Container(
      width: 150,
      height: 150,
      color: Colors.blue,
    ),
  ],
)

The widgets overlap each other. The first child is painted first, and later children appear above earlier children.

5. Stack Layer Order

The order of children in a Stack determines their visual layering.

Stack(
  children: [
    BackgroundWidget(), // Bottom layer
    ImageWidget(),      // Middle layer
    TextWidget(),       // Top layer
  ],
)

The first child is at the bottom and subsequent children are painted above it.

6. What Is the Positioned Widget?

Positioned controls where a child is placed inside a Stack. It provides properties such as top, right, bottom, left, width, and height.

A Positioned widget must be a descendant of a Stack.

7. Basic Positioned Syntax

Stack(
  children: [
    Container(
      width: 300,
      height: 300,
      color: Colors.grey,
    ),
    Positioned(
      top: 20,
      left: 20,
      child: Container(
        width: 80,
        height: 80,
        color: Colors.blue,
      ),
    ),
  ],
)

The blue container is positioned 20 logical pixels from the top and 20 logical pixels from the left of the Stack.

8. Positioned Properties

PropertyPurpose
topDistance from the top edge of the Stack.
rightDistance from the right edge of the Stack.
bottomDistance from the bottom edge of the Stack.
leftDistance from the left edge of the Stack.
widthSpecifies the child's width.
heightSpecifies the child's height.
childThe widget being positioned.

9. Positioned with top and left

Stack(
  children: [
    Container(
      width: 300,
      height: 200,
      color: Colors.grey,
    ),
    Positioned(
      top: 20,
      left: 30,
      child: Container(
        width: 100,
        height: 60,
        color: Colors.blue,
      ),
    ),
  ],
)

Here, the child starts 20 pixels from the top and 30 pixels from the left.

10. Positioned with top and right

Positioned(
  top: 20,
  right: 20,
  child: Container(
    width: 80,
    height: 80,
    color: Colors.red,
  ),
)

This places the widget near the top-right corner of the Stack.

11. Positioned with bottom and left

Positioned(
  bottom: 20,
  left: 20,
  child: Container(
    width: 80,
    height: 80,
    color: Colors.green,
  ),
)

This places the widget near the bottom-left corner.

12. Positioned with bottom and right

Positioned(
  bottom: 20,
  right: 20,
  child: Container(
    width: 80,
    height: 80,
    color: Colors.orange,
  ),
)

This places the widget near the bottom-right corner.

13. Centering a Widget in Stack

A widget can be centered using the Stack's alignment property.

Stack(
  alignment: Alignment.center,
  children: [
    Container(
      width: 300,
      height: 200,
      color: Colors.blue,
    ),
    const Text(
      'Centered Text',
      style: TextStyle(
        color: Colors.white,
        fontSize: 24,
      ),
    ),
  ],
)

14. Using Positioned with Width and Height

You can specify the dimensions of a positioned child using width and height.

Stack(
  children: [
    Container(
      width: 300,
      height: 300,
      color: Colors.grey,
    ),
    Positioned(
      top: 30,
      left: 30,
      width: 120,
      height: 80,
      child: Container(
        color: Colors.blue,
      ),
    ),
  ],
)

15. Using Left and Right Together

When both left and right are provided, they can determine the horizontal size of the positioned child.

Stack(
  children: [
    Container(
      width: 350,
      height: 200,
      color: Colors.grey,
    ),
    Positioned(
      left: 20,
      right: 20,
      bottom: 20,
      height: 50,
      child: Container(
        color: Colors.black,
        child: const Center(
          child: Text(
            'Bottom Content',
            style: TextStyle(color: Colors.white),
          ),
        ),
      ),
    ),
  ],
)

16. Using Top and Bottom Together

When both top and bottom are provided, they can determine the vertical size of the child.

Stack(
  children: [
    Container(
      width: 300,
      height: 300,
      color: Colors.grey,
    ),
    Positioned(
      top: 30,
      bottom: 30,
      left: 30,
      width: 100,
      child: Container(
        color: Colors.blue,
      ),
    ),
  ],
)

17. Positioned.fill

Positioned.fill is a convenient constructor that positions a child so that its default left, top, right, and bottom values are zero.

This is especially useful when creating an overlay that should cover the entire Stack.

Stack(
  children: [
    Container(
      width: 300,
      height: 200,
      color: Colors.blue,
    ),
    Positioned.fill(
      child: Container(
        color: Colors.black54,
      ),
    ),
  ],
)

18. Image Overlay Using Stack

One of the most common uses of Stack is placing text over an image.

Stack(
  children: [
    Image.network(
      'https://example.com/image.jpg',
      width: double.infinity,
      height: 250,
      fit: BoxFit.cover,
    ),
    const Positioned(
      left: 20,
      bottom: 20,
      child: Text(
        'Beautiful Landscape',
        style: TextStyle(
          color: Colors.white,
          fontSize: 24,
          fontWeight: FontWeight.bold,
        ),
      ),
    ),
  ],
)

19. Image with Gradient Overlay

A gradient overlay can improve text readability on images.

Stack(
  children: [
    Image.network(
      'https://example.com/image.jpg',
      width: double.infinity,
      height: 300,
      fit: BoxFit.cover,
    ),
    Positioned.fill(
      child: Container(
        decoration: BoxDecoration(
          gradient: LinearGradient(
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
            colors: [
              Colors.transparent,
              Colors.black87,
            ],
          ),
        ),
      ),
    ),
    const Positioned(
      left: 20,
      bottom: 20,
      child: Text(
        'Flutter UI Design',
        style: TextStyle(
          color: Colors.white,
          fontSize: 26,
          fontWeight: FontWeight.bold,
        ),
      ),
    ),
  ],
)

20. Profile Picture with Online Badge

Stack is useful for placing a status badge over a profile picture.

Stack(
  children: [
    const CircleAvatar(
      radius: 45,
      backgroundImage: NetworkImage(
        'https://example.com/profile.jpg',
      ),
    ),
    Positioned(
      right: 0,
      bottom: 0,
      child: Container(
        width: 20,
        height: 20,
        decoration: BoxDecoration(
          color: Colors.green,
          shape: BoxShape.circle,
          border: Border.all(
            color: Colors.white,
            width: 3,
          ),
        ),
      ),
    ),
  ],
)

21. Notification Badge

A notification count can be placed over an icon using Stack and Positioned.

Stack(
  clipBehavior: Clip.none,
  children: [
    const Icon(
      Icons.notifications,
      size: 35,
    ),
    Positioned(
      right: -5,
      top: -5,
      child: Container(
        padding: const EdgeInsets.all(5),
        decoration: const BoxDecoration(
          color: Colors.red,
          shape: BoxShape.circle,
        ),
        child: const Text(
          '5',
          style: TextStyle(
            color: Colors.white,
            fontSize: 12,
          ),
        ),
      ),
    ),
  ],
)

22. Floating Action Button Style Overlay

Stack(
  children: [
    Container(
      width: double.infinity,
      height: 300,
      color: Colors.blueGrey,
    ),
    Positioned(
      right: 20,
      bottom: 20,
      child: FloatingActionButton(
        onPressed: () {},
        child: const Icon(Icons.add),
      ),
    ),
  ],
)

23. Product Card Using Stack

Card(
  clipBehavior: Clip.antiAlias,
  child: Stack(
    children: [
      Image.network(
        'https://example.com/product.jpg',
        width: double.infinity,
        height: 250,
        fit: BoxFit.cover,
      ),
      Positioned(
        top: 12,
        right: 12,
        child: Container(
          padding: const EdgeInsets.symmetric(
            horizontal: 10,
            vertical: 6,
          ),
          decoration: BoxDecoration(
            color: Colors.red,
            borderRadius: BorderRadius.circular(20),
          ),
          child: const Text(
            '20% OFF',
            style: TextStyle(
              color: Colors.white,
              fontWeight: FontWeight.bold,
            ),
          ),
        ),
      ),
      const Positioned(
        left: 15,
        bottom: 15,
        child: Text(
          'Smart Watch',
          style: TextStyle(
            color: Colors.white,
            fontSize: 22,
            fontWeight: FontWeight.bold,
          ),
        ),
      ),
    ],
  ),
)

24. Stack Alignment

The alignment property controls how non-positioned and partially positioned children are aligned.

Stack(
  alignment: Alignment.center,
  children: [
    Container(
      width: 250,
      height: 250,
      color: Colors.blue,
    ),
    const Icon(
      Icons.favorite,
      color: Colors.white,
      size: 60,
    ),
  ],
)

Common Alignment Values

  • Alignment.topLeft
  • Alignment.topCenter
  • Alignment.topRight
  • Alignment.centerLeft
  • Alignment.center
  • Alignment.centerRight
  • Alignment.bottomLeft
  • Alignment.bottomCenter
  • Alignment.bottomRight

25. StackFit

The fit property controls how non-positioned children are sized inside the Stack.

Stack(
  fit: StackFit.expand,
  children: [
    Container(
      color: Colors.blue,
    ),
    const Center(
      child: Text(
        'Full Size Background',
        style: TextStyle(color: Colors.white),
      ),
    ),
  ],
)

Common StackFit Values

ValueDescription
StackFit.looseChildren receive loose constraints.
StackFit.expandNon-positioned children are forced to fill the Stack's available space.
StackFit.passthroughPasses the constraints received by the Stack to its non-positioned children.

26. Clip Behavior

The clipBehavior property controls whether content that extends outside the Stack's bounds is clipped.

Stack(
  clipBehavior: Clip.none,
  children: [
    Container(
      width: 200,
      height: 200,
      color: Colors.blue,
    ),
    Positioned(
      right: -20,
      top: -20,
      child: const CircleAvatar(
        radius: 30,
        child: Icon(Icons.star),
      ),
    ),
  ],
)

Clip.none is useful when a badge or decorative element intentionally extends outside the Stack.

27. Stack with Container Background

Stack(
  children: [
    Container(
      width: double.infinity,
      height: 250,
      decoration: BoxDecoration(
        color: Colors.blue,
        borderRadius: BorderRadius.circular(20),
      ),
    ),
    const Positioned(
      left: 20,
      top: 20,
      child: Text(
        'Welcome',
        style: TextStyle(
          color: Colors.white,
          fontSize: 28,
          fontWeight: FontWeight.bold,
        ),
      ),
    ),
    const Positioned(
      left: 20,
      bottom: 20,
      child: Text(
        'Welcome to Flutter',
        style: TextStyle(
          color: Colors.white70,
          fontSize: 16,
        ),
      ),
    ),
  ],
)

28. Stack Inside a SizedBox

A Stack often works best when its available size is clearly defined by its parent.

SizedBox(
  width: 300,
  height: 200,
  child: Stack(
    children: [
      Container(
        color: Colors.grey,
      ),
      const Positioned(
        top: 20,
        left: 20,
        child: Text('Top Left'),
      ),
      const Positioned(
        bottom: 20,
        right: 20,
        child: Text('Bottom Right'),
      ),
    ],
  ),
)

29. Stack Inside a Card

Card(
  child: SizedBox(
    height: 220,
    child: Stack(
      children: [
        Container(
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(12),
            color: Colors.indigo,
          ),
        ),
        const Positioned(
          left: 20,
          top: 20,
          child: Icon(
            Icons.flutter_dash,
            color: Colors.white,
            size: 50,
          ),
        ),
        const Positioned(
          left: 20,
          bottom: 20,
          child: Text(
            'Flutter Course',
            style: TextStyle(
              color: Colors.white,
              fontSize: 22,
            ),
          ),
        ),
      ],
    ),
  ),
)

30. Stack with Multiple Positioned Widgets

Stack(
  children: [
    Container(
      width: 350,
      height: 250,
      color: Colors.grey,
    ),
    Positioned(
      top: 10,
      left: 10,
      child: Container(
        width: 70,
        height: 70,
        color: Colors.red,
      ),
    ),
    Positioned(
      top: 10,
      right: 10,
      child: Container(
        width: 70,
        height: 70,
        color: Colors.green,
      ),
    ),
    Positioned(
      bottom: 10,
      left: 10,
      child: Container(
        width: 70,
        height: 70,
        color: Colors.blue,
      ),
    ),
    Positioned(
      bottom: 10,
      right: 10,
      child: Container(
        width: 70,
        height: 70,
        color: Colors.orange,
      ),
    ),
  ],
)

31. Responsive Stack Layout

Stack can also be used in responsive layouts. Instead of relying on fixed dimensions everywhere, allow the parent to provide constraints and use widgets such as Positioned.fill and MediaQuery or LayoutBuilder when layout decisions are required.

LayoutBuilder(
  builder: (context, constraints) {
    final isSmall = constraints.maxWidth < 600;

    return SizedBox(
      height: isSmall ? 220 : 350,
      width: double.infinity,
      child: Stack(
        children: [
          Positioned.fill(
            child: Container(
              color: Colors.blueGrey,
            ),
          ),
          Positioned(
            left: isSmall ? 16 : 40,
            bottom: isSmall ? 16 : 30,
            child: Text(
              isSmall ? 'Mobile' : 'Large Screen',
              style: const TextStyle(
                color: Colors.white,
                fontSize: 24,
              ),
            ),
          ),
        ],
      ),
    );
  },
)

32. Stack with Positioned.fill and Overlay

Stack(
  children: [
    Image.network(
      'https://example.com/banner.jpg',
      width: double.infinity,
      height: 300,
      fit: BoxFit.cover,
    ),
    Positioned.fill(
      child: Container(
        color: Colors.black45,
      ),
    ),
    const Center(
      child: Text(
        'Flutter Development',
        style: TextStyle(
          color: Colors.white,
          fontSize: 30,
          fontWeight: FontWeight.bold,
        ),
      ),
    ),
  ],
)

33. Stack with Button Overlay

Stack(
  children: [
    Container(
      height: 250,
      width: double.infinity,
      color: Colors.blueGrey,
    ),
    const Positioned(
      left: 20,
      top: 20,
      child: Text(
        'Featured Course',
        style: TextStyle(
          color: Colors.white,
          fontSize: 24,
        ),
      ),
    ),
    Positioned(
      right: 20,
      bottom: 20,
      child: ElevatedButton(
        onPressed: () {},
        child: const Text('Learn More'),
      ),
    ),
  ],
)

34. Creating a Badge Widget

Widget buildBadge(String text) {
  return Container(
    padding: const EdgeInsets.symmetric(
      horizontal: 10,
      vertical: 5,
    ),
    decoration: BoxDecoration(
      color: Colors.red,
      borderRadius: BorderRadius.circular(20),
    ),
    child: Text(
      text,
      style: const TextStyle(
        color: Colors.white,
        fontWeight: FontWeight.bold,
      ),
    ),
  );
}

Stack(
  children: [
    Container(
      width: 250,
      height: 150,
      color: Colors.blue,
    ),
    Positioned(
      top: 10,
      right: 10,
      child: buildBadge('NEW'),
    ),
  ],
)

35. Complete Profile Card Example

import 'package:flutter/material.dart';

void main() {
  runApp(const ProfileApp());
}

class ProfileApp extends StatelessWidget {
  const ProfileApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: const ProfileScreen(),
    );
  }
}

class ProfileScreen extends StatelessWidget {
  const ProfileScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Profile'),
      ),
      body: Center(
        child: Card(
          margin: const EdgeInsets.all(20),
          child: SizedBox(
            width: 350,
            height: 300,
            child: Stack(
              children: [
                Positioned.fill(
                  child: Container(
                    decoration: BoxDecoration(
                      gradient: const LinearGradient(
                        colors: [
                          Colors.blue,
                          Colors.indigo,
                        ],
                      ),
                      borderRadius: BorderRadius.circular(16),
                    ),
                  ),
                ),
                const Positioned(
                  top: 30,
                  left: 0,
                  right: 0,
                  child: CircleAvatar(
                    radius: 50,
                    child: Icon(
                      Icons.person,
                      size: 55,
                    ),
                  ),
                ),
                const Positioned(
                  top: 145,
                  left: 0,
                  right: 0,
                  child: Text(
                    'Manish',
                    textAlign: TextAlign.center,
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 24,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
                const Positioned(
                  top: 180,
                  left: 0,
                  right: 0,
                  child: Text(
                    'Flutter Developer',
                    textAlign: TextAlign.center,
                    style: TextStyle(
                      color: Colors.white70,
                      fontSize: 16,
                    ),
                  ),
                ),
                Positioned(
                  bottom: 25,
                  left: 30,
                  right: 30,
                  child: ElevatedButton(
                    onPressed: () {},
                    child: const Text('View Profile'),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

36. Stack vs Row vs Column

WidgetLayout TypeCommon Use
RowHorizontalIcons, buttons, horizontal content
ColumnVerticalForms, text sections, vertical content
StackLayered/overlappingOverlays, badges, floating elements
PositionedPrecise placement inside StackTop, bottom, left and right positioning

37. Stack vs Positioned

StackPositioned
Creates a layered layout.Controls the position of a child inside Stack.
Can contain multiple children.Wraps one child.
Controls alignment and overall layering.Controls top, right, bottom, left, width and height.
Can contain positioned and non-positioned children.Must be used as a descendant of Stack.

38. Important Stack Rules

  • Stack is primarily used for overlapping widgets.
  • The order of children controls the painting order.
  • The first child is painted at the bottom.
  • Later children are painted above earlier children.
  • Positioned widgets should be descendants of Stack.
  • Non-positioned children contribute to the Stack's size.
  • Use alignment for general alignment of non-positioned children.
  • Use Positioned for explicit placement.
  • Use Positioned.fill for full-area overlays.
  • Use Clip.none when an intentionally positioned element needs to extend outside the Stack.

39. Common Mistakes

Mistake 1: Using Positioned Outside Stack

Column(
  children: [
    Positioned(
      top: 10,
      child: Text('Incorrect'),
    ),
  ],
)

This is incorrect because Positioned is designed to provide positioning information to a Stack.

Mistake 2: Expecting Stack to Automatically Scroll

Stack itself is not a scrolling widget. If the content needs to scroll, place the appropriate scrollable widget around the layout.

Mistake 3: Excessive Absolute Positioning

Using many hard-coded top and left values can make a UI difficult to maintain across screen sizes. Use responsive constraints and layout widgets where appropriate.

Mistake 4: Forgetting Stack Size

A Stack needs appropriate constraints from its parent. If its size is not determined by its parent or non-positioned children, the resulting layout may not behave as expected.

Mistake 5: Incorrect Layer Order

If a background widget is placed after the foreground widget, it may paint over the foreground. Check the order of children in the Stack.

40. Stack with SafeArea

For interfaces that contain content near system areas such as notches and status bars, SafeArea can be combined with Stack.

Scaffold(
  body: SafeArea(
    child: Stack(
      children: [
        Positioned.fill(
          child: Container(
            color: Colors.blue,
          ),
        ),
        const Positioned(
          top: 20,
          left: 20,
          child: Text(
            'Safe Content',
            style: TextStyle(
              color: Colors.white,
              fontSize: 24,
            ),
          ),
        ),
      ],
    ),
  ),
)

41. AnimatedPositioned

When a positioned widget needs to move with animation, Flutter provides AnimatedPositioned.

AnimatedPositioned(
  duration: const Duration(milliseconds: 500),
  left: isExpanded ? 100 : 20,
  top: 20,
  child: Container(
    width: 80,
    height: 80,
    color: Colors.blue,
  ),
)

AnimatedPositioned is useful for interactive cards, expandable panels, custom menus, badges, and simple movement animations.

42. Stack in Real-World Applications

  • Profile image status indicators
  • Notification badges
  • Product sale labels
  • Image captions
  • Image gradients
  • Floating action controls
  • Video player overlays
  • Map markers and overlays
  • Custom dashboard cards
  • Onboarding screens
  • Hero banners
  • Decorative UI elements
  • Custom loading overlays
  • Interactive cards

43. Best Practices

  1. Use Stack when elements genuinely need to overlap.
  2. Use Row and Column for normal one-dimensional layouts.
  3. Use Positioned only when explicit positioning is required.
  4. Prefer constraints over excessive fixed coordinates.
  5. Use Positioned.fill for full-area overlays.
  6. Use LayoutBuilder when Stack content needs to adapt to available width.
  7. Keep the Stack hierarchy simple.
  8. Use meaningful widget names for complex layered layouts.
  9. Test positioned layouts on different screen sizes.
  10. Consider accessibility when placing interactive elements on top of other content.

44. Practice Exercises

  1. Create a Stack containing three overlapping colored containers.
  2. Create a profile picture with an online status badge.
  3. Create a product card with a "20% OFF" badge.
  4. Create an image banner with text positioned at the bottom.
  5. Create an image with a dark gradient overlay.
  6. Create a notification icon with a red count badge.
  7. Create a Stack with four widgets positioned at its four corners.
  8. Create a responsive banner using Stack and LayoutBuilder.
  9. Create an animated badge using AnimatedPositioned.
  10. Create a profile card using Stack, Positioned, and Positioned.fill.

45. Interview Questions

Q1. What is Stack in Flutter?

Stack is a widget used to position multiple children relative to its box and allows those children to overlap.

Q2. What is Positioned?

Positioned controls the location of a child inside a Stack using properties such as top, right, bottom, left, width, and height.

Q3. Can Positioned be used without Stack?

Positioned is designed to be a descendant of Stack and should not be used as a general-purpose positioning widget outside a Stack.

Q4. What determines the order of layers in Stack?

The order of children in the Stack determines the painting order. Later children are painted above earlier children.

Q5. What is Positioned.fill?

Positioned.fill is a convenient constructor that defaults the left, top, right, and bottom insets to zero, allowing the child to fill the Stack's available area.

Q6. What is the difference between Stack and Column?

Column arranges children vertically, while Stack allows children to overlap and be positioned relative to the Stack.

Q7. What is AnimatedPositioned?

AnimatedPositioned is an animated version of Positioned that transitions position changes over a specified duration.

46. Useful Flutter Documentation

47. Flutter Training Resources

For structured Flutter learning, practical development training, and course information, visit the following resources:

48. Summary

Stack is one of Flutter's most useful widgets for creating layered interfaces. It allows multiple children to overlap, while Positioned provides precise control over where individual children appear within the Stack.

The most important properties of Positioned are top, right, bottom, left, width, and height. Positioned.fill is useful for full-area overlays, while Stack's alignment, fit, and clipBehavior properties provide additional control over the layout.

By combining Stack and Positioned with responsive techniques such as LayoutBuilder, flexible constraints, and appropriate sizing, developers can create professional interfaces such as profile cards, product cards, image banners, notification badges, overlays, and custom dashboard components.


Key Formula: Stack = Layered Layout + Positioned = Precise Placement + Responsive Constraints = Flexible UI

whatsapp